package com.xclink.common.service;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;

import javax.persistence.Id;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xclink.common.config.AppConfig;
import com.xclink.sys.entity.User;

import tk.mybatis.mapper.common.Mapper;

public abstract class AbstractService<T> {
	@Autowired
	private HttpServletRequest request;
	@Autowired
	private HttpSession session;
	@Autowired
	private AppConfig config;

	// 泛型注入实现
	// @Autowired
	// public Mapper<T> mapper;
	// 模版方式实现（注意：如果使用模版方式，需要把所有的mapper改为getMapper()）
	public abstract Mapper<T> getMapper();

	/**
	 * 保存一个实体，null的属性也会保存，不会使用数据库默认值
	 * 
	 * @param entity(实体对象)
	 * @return 返回结果
	 * @throws Exception
	 */
	public int save(T entity) throws Exception {
		try {
			User user = (User) session.getAttribute("currentUser");
			Class<?> claszz = entity.getClass();

			Field createBy = claszz.getDeclaredField("createBy");
			createBy.setAccessible(true);
			createBy.set(entity, user.getUserId());

			Field lastUpdateBy = claszz.getDeclaredField("lastUpdateBy");
			lastUpdateBy.setAccessible(true);
			lastUpdateBy.set(entity, user.getUserId());

			Field createTime = claszz.getDeclaredField("createTime");
			createTime.setAccessible(true);
			createTime.set(entity, new Date());

			Field lastUpdateTime = claszz.getDeclaredField("lastUpdateTime");
			lastUpdateTime.setAccessible(true);
			lastUpdateTime.set(entity, new Date());
		} catch (Exception e) {
			// e.printStackTrace();
		}
		return getMapper().insert(entity);
	}

	/**
	 * 保存一个实体，null的属性不会保存，会使用数据库默认值
	 * 
	 * @param entity(实体对象)
	 * @return 返回结果
	 * @throws Exception
	 */
	public int saveNotNull(T entity) throws Exception {
		try {
			User user = (User) session.getAttribute("currentUser");
			Class<?> claszz = entity.getClass();

			Field createBy = claszz.getDeclaredField("createBy");
			createBy.setAccessible(true);
			createBy.set(entity, user.getUserId());

			Field lastUpdateBy = claszz.getDeclaredField("lastUpdateBy");
			lastUpdateBy.setAccessible(true);
			lastUpdateBy.set(entity, user.getUserId());

			Field createTime = claszz.getDeclaredField("createTime");
			createTime.setAccessible(true);
			createTime.set(entity, new Date());

			Field lastUpdateTime = claszz.getDeclaredField("lastUpdateTime");
			lastUpdateTime.setAccessible(true);
			lastUpdateTime.set(entity, new Date());
		} catch (Exception e) {
			// e.printStackTrace();
		}
		return getMapper().insertSelective(entity);
	}

	/**
	 * 根据主键更新实体全部字段，null值会被更新
	 * 
	 * @param entity(实体对象)
	 * @return 返回结果
	 * @throws Exception
	 */
	public int update(T entity) throws Exception {
		try {
			User user = (User) session.getAttribute("currentUser");
			Class<?> claszz = entity.getClass();

			Field lastUpdateBy = claszz.getDeclaredField("lastUpdateBy");
			lastUpdateBy.setAccessible(true);
			lastUpdateBy.set(entity, user.getUserId());

			Field lastUpdateTime = claszz.getDeclaredField("lastUpdateTime");
			lastUpdateTime.setAccessible(true);
			lastUpdateTime.set(entity, new Date());
		} catch (Exception e) {
			// e.printStackTrace();
		}

		return getMapper().updateByPrimaryKey(entity);
	}

	/**
	 * 根据主键更新属性不为null的值
	 * 
	 * @param entity(实体对象)
	 * @return 返回结果
	 * @throws Exception
	 */
	public int updateNotNull(T entity) throws Exception {
		try {
			User user = (User) session.getAttribute("currentUser");
			Class<?> claszz = entity.getClass();

			Field lastUpdateBy = claszz.getDeclaredField("lastUpdateBy");
			lastUpdateBy.setAccessible(true);
			lastUpdateBy.set(entity, user.getUserId());

			Field lastUpdateTime = claszz.getDeclaredField("lastUpdateTime");
			lastUpdateTime.setAccessible(true);
			lastUpdateTime.set(entity, new Date());
		} catch (Exception e) {
			// e.printStackTrace();
		}
		return getMapper().updateByPrimaryKeySelective(entity);
	}

	/**
	 * 根据主键更新实体全部字段，null值会被更新
	 * 
	 * @param record
	 * @return
	 */
	public int saveOrUpdate(T entity) throws Exception {

		Object id = null;
		try {
			Class<?> claszz = entity.getClass();
			id = claszz.getDeclaredField(getPrimaryKeyName(entity)).get(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (StringUtils.isEmpty(id)) {
			return save(entity);
		} else {
			return update(entity);
		}
	}

	/**
	 * 根据主键更新实体全部字段，null值不会被更新
	 * 
	 * @param record
	 * @return
	 */
	public int saveOrUpdateNotNull(T entity) throws Exception {
		Object id = null;
		try {
			Class<?> claszz = entity.getClass();
			Field field = claszz.getDeclaredField(getPrimaryKeyName(entity));
			field.setAccessible(true);
			id = field.get(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (StringUtils.isEmpty(id)) {
			return saveNotNull(entity);
		} else {
			return updateNotNull(entity);
		}
	}
	

	
	
	

	/**
	 * 根据主键字段进行删除，方法参数必须包含完整的主键属性
	 * 
	 * @param key(主键)
	 * @return 返回结果
	 * @throws Exception
	 */
	public int deleteByPrimaryKey(Object key) throws Exception {
		return getMapper().deleteByPrimaryKey(key);
	}

	/**
	 * 根据实体属性作为条件进行删除，查询条件使用等号
	 * 
	 * @param entity(实体对象)
	 * @return 返回结果
	 * @throws Exception
	 */
	public int delete(T entity) throws Exception {
		return getMapper().delete(entity);
	}

	/**
	 * 根据主键进行批量删除
	 * 
	 * @param list(主键集合)
	 * @return 返回结果(0代表失败)
	 * @throws Exception
	 */
	public int deleteByLongIds(List<Long> list) throws Exception {
		int i = 0;
		for (Long key : list) {
			i = getMapper().deleteByPrimaryKey(key);
		}
		return i;
	}
	public int deleteByStringIds(List<String> list) throws Exception {
		int i = 0;
		for (String key : list) {
			i = getMapper().deleteByPrimaryKey(key);
		}
		return i;
	}
	public int deleteByIntIds(List<Integer> list) throws Exception {
		int i = 0;
		for (Integer key : list) {
			i = getMapper().deleteByPrimaryKey(key);
		}
		return i;
	}

	/**
	 * 根据主键字段进行查询，方法参数必须包含完整的主键属性，查询条件使用等号
	 * 
	 * @param key(主键)
	 * @return 返回结果
	 */
	public T get(Object key) {
		return getMapper().selectByPrimaryKey(key);
	}

	/**
	 * 查询全部结果
	 * 
	 * @return 返回结果
	 */
	public List<T> findAll() {
		return getMapper().selectAll();
	}

	/**
	 * 根据实体中的属性进行查询，只能有一个返回值，有多个结果是抛出异常，查询条件使用等号
	 * 
	 * @param entity(实体对象)
	 * @return 返回结果
	 */
	public T findOne(T entity) {
		return getMapper().selectOne(entity);
	}

	/**
	 * 根据实体中的属性值进行查询
	 * 
	 * @param entity(实体对象)
	 * @return 返回结果
	 */
	public abstract List<T> find(T entity);

	/**
	 * 根据实体中的属性值进行查询带分页
	 * 
	 * @param entity(实体对象)
	 * @param pageNum(页码)
	 * @param pageSize(每页显示的条数)
	 * @return 返回结果
	 */
	public List<T> find(T entity, Integer pageNum, Integer pageSize) {
		return getMapper().selectByRowBounds(entity, new RowBounds(pageNum, pageSize));
	}

	/**
	 * 查询条数
	 * 
	 * @param entity(实体对象)
	 * @return 返回结果
	 */
	public int findCount(T entity) {
		return getMapper().selectCount(entity);
	}

	/**
	 * 根据实体中的属性值进行分页查询，返回PageInfo对象
	 * 
	 * @param entity(实体对象)
	 * @param pageNum(页码)
	 * @param pageSize(每页显示的条数)
	 * @return 返回结果
	 */
	public PageInfo<T> findPageInfo(T entity, Integer pageNum, Integer pageSize) {
		if (pageNum == null) {
			pageNum = Integer.parseInt(config.getValue("pageNum"));
		}
		if (pageSize == null) {
			pageSize = Integer.parseInt(config.getValue("pageSize"));
		}
		PageHelper.startPage(pageNum, pageSize);
		List<T> list = find(entity);
		return new PageInfo<T>(list);
	}

	/**
	 * 根据Example条件进行查询
	 * 
	 * @param example(查询条件)
	 * @return 返回结果
	 */
	public List<T> findByExample(Object example) {
		return getMapper().selectByExample(example);
	}

	/**
	 * 根据example条件进行分页查询
	 * 
	 * @param example(查询条件)
	 * @param pageNum(页码)
	 * @param pageSize(每页显示的条数)
	 * @return 返回结果
	 */
	public List<T> findByExample(Object example, int pageNum, int pageSize) {
		return getMapper().selectByExampleAndRowBounds(example, new RowBounds(pageNum, pageSize));
	}

	/**
	 * 根据Example条件进行查询总数
	 * 
	 * @param example(查询条件)
	 * @return 返回结果
	 */
	public int findCountByExample(Object example) {
		return getMapper().selectCountByExample(example);
	}

	/**
	 * 根据Example条件进行分页查询，查询条件使用等号，返回PageInfo对象
	 * 
	 * @param example(查询条件)
	 * @param pageNum(页码)
	 * @param pageSize(每页显示的条数)
	 * @return 返回结果
	 */
	public PageInfo<T> findPageInfoByExample(Object example, Integer pageNum, Integer pageSize) {
		if (pageNum == null) {
			pageNum = Integer.parseInt(config.getValue("pageNum"));
		}
		if (pageSize == null) {
			pageSize = Integer.parseInt(config.getValue("pageSize"));
		}
		PageHelper.startPage(pageNum, pageSize);
		List<T> list = findByExample(example);
		return new PageInfo<T>(list);
	}

	/**
	 * 获取主键对应的实体对象的属性名称
	 * 
	 * @return
	 */
	public String getPrimaryKeyName(T entity) {
		Field[] fields = entity.getClass().getDeclaredFields();
		String name = "";
		for (Field f : fields) {
			Id hidden = f.getAnnotation(Id.class);
			if (hidden != null) {
				name = f.getName();
				break;
			}
		}
		return name;
	}

}